#include "aerOpenGL.hpp"
#include <iostream>


namespace aer {
namespace gl {

bool Initialize()
{
  glewExperimental = GL_TRUE;
  
  GLenum result = glewInit();  
  if (GLEW_OK != result)
  {
    fprintf( stderr, "Error: %s\n", glewGetErrorString(result));
    return false;
  }

# ifndef NDEBUG
  fprintf( stderr, "----------------------------------------------------\n");
  fprintf( stderr, "[ Debug ]\n");
  fprintf( stderr, "GLEW version : %s\n", glewGetString(GLEW_VERSION));
  fprintf( stderr, "OpenGL version : %s\n", Info::GetVersion());
  fprintf( stderr, "GLSL version : %s\n", Info::GetGLSLVersion());
  fprintf( stderr, "Device : %s\n", Info::GetRenderer());
  fprintf( stderr, "----------------------------------------------------\n\n");
# endif

  // sometimes the error handler is not initialized
  glGetError();
  
  return true;
}

const int Geti( GLenum pname )
{
  GLint param;
  glGetIntegerv( pname, &param);
  return param;
}

const char* GetErrorString(GLenum err)
{
  switch (err)
  {
    // [GetError]
    case GL_NO_ERROR:
      return AER_STRINGIFY(GL_NO_ERROR);
      
    case GL_INVALID_ENUM:
      return AER_STRINGIFY(GL_INVALID_ENUM);
      
    case GL_INVALID_VALUE:
      return AER_STRINGIFY(GL_INVALID_VALUE);
      
    case GL_INVALID_OPERATION:
      return AER_STRINGIFY(GL_INVALID_OPERATION);
      
    case GL_STACK_OVERFLOW:
      return AER_STRINGIFY(GL_STACK_OVERFLOW);
      
    case GL_STACK_UNDERFLOW:
      return AER_STRINGIFY(GL_STACK_UNDERFLOW);
      
    case GL_OUT_OF_MEMORY:
      return AER_STRINGIFY(GL_OUT_OF_MEMORY);
      
    case GL_TABLE_TOO_LARGE:
      return AER_STRINGIFY(GL_TABLE_TOO_LARGE);
      
              
    // [CheckFramebufferStatus]
    case GL_FRAMEBUFFER_COMPLETE:
      return AER_STRINGIFY(GL_FRAMEBUFFER_COMPLETE);
      
    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
      return AER_STRINGIFY(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
      
    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
      return AER_STRINGIFY(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
      
    case GL_FRAMEBUFFER_UNSUPPORTED:
      return AER_STRINGIFY(GL_FRAMEBUFFER_UNSUPPORTED);
      
      
    default:
      return "GetErrorString : Unknown constant";
  }  
    
  return "";
}

void CheckError(const char *file, const int line, const char *errMsg, bool bExitOnFail)
{
  GLenum err = glGetError();

  if (err != GL_NO_ERROR)
  {
    std::cerr << "OpenGL error @ " 
              << file << "[" << line << "] : "
              << errMsg 
              << " [ " << GetErrorString( err ) << " ] "
              << std::endl;
    
    if (bExitOnFail) {
      exit( EXIT_FAILURE );
    }
  }
}


} // gl
} // aer
